package com.powernode.sqlinjection;

import com.powernode.commons.util.DbUtils;

import java.sql.*;
import java.util.Scanner;

@SuppressWarnings("all")
/**
 * @Author Arrebol
 * @Date 2024/8/1 21:23
 * @Project jdbc
 * @Description： 模拟用户登录功能
 * 此程序会有SQL注入的风险，在当前登录系统中的SQL注入情况为：用户输入的信息中含有SQL语句的关键字,
 * 作为字符串的形式与Java程序中的SQL语句进行了字符串的拼接, 可能会导致原先SQL语句的含义被扭曲,
 * 所以可以通过输入特定的内容，扭曲原先的MySQL的DQL语句。
 *
 * 导致SQL注入的原因是先进行了SQL语句的字符串拼接，然后才进行SQL语句的编译。
 * 为了解决此隐患，JDBC API中为Statement接口提供了一个子接口，java.sql.PreparedStatement，
 * 称为预编译的数据库操作对象。其可以对SQL语句进行预先编译，然后给编译好的SQL语句占位符传值。
 * 所以最本质的方法是，用户即使提供了SQL语句的关键字，但是这些SQL语句不再参与SQL语句的编译。
 */
public class JdbcTest1Login {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            conn = DbUtils.getConnection();
            stmt = conn.createStatement();
            System.out.println("请输入用户名和密码");
            var sc = new Scanner(System.in);
            String username = sc.nextLine();
            String password = sc.nextLine();
            String querySql = "select * from t_user where username = '" + username + "' and password = '" + password + "'";
            System.out.println("执行的SQL语句为：" + querySql);
            rs = stmt.executeQuery(querySql);
            //如果结果集中有数据，即登录成功
            if (!rs.next()) {
                System.out.println("用户名或密码错误，登录失败");
            } else {
                System.out.println("登录成功！");
                System.out.println("欢迎用户 " + rs.getString("username"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.close(rs, stmt, conn);
        }
    }
}
